package com.zys.el.time.service.impl;

import cn.hutool.core.lang.Snowflake;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zys.el.time.common.exception.CustomException;
import com.zys.el.time.common.exception.sql.SqlException;
import com.zys.el.time.constants.MQConstants;
import com.zys.el.time.constants.RedisConstants;
import com.zys.el.time.dto.ScrollPage;
import com.zys.el.time.entity.Thinking;
import com.zys.el.time.mapper.CommentMapper;
import com.zys.el.time.mapper.ThinkingMapper;
import com.zys.el.time.mq.constants.ModeType;
import com.zys.el.time.mq.dto.MqDTO;
import com.zys.el.time.service.ThinkingService;
import com.zys.el.time.service.lambda_like.ILambdaLikeService;
import com.zys.el.time.service.redis.CacheClient;
import com.zys.el.time.vojo.ThinkingVo;
import com.zys.el.time.vojo.UserVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class ThinkingServiceImpl extends ServiceImpl<ThinkingMapper, Thinking>
        implements ThinkingService {
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private RabbitTemplate rabbitTemplate;
    @Resource
    private CacheClient cacheClient;
    @Resource
    private UserService userService;

    @Override
    public ThinkingVo getThinkingVoById(Long thinkingId) {
        // 查询缓存
        String thinkingKey = RedisConstants.THINKING_KEY + thinkingId;

        Thinking thinking = cacheClient.queryWithoutLock(thinkingKey, thinkingId, Thinking.class,
                this::getById, RedisConstants.THINKING_TTL, RedisConstants.THINKING_NULL_TTL, TimeUnit.MINUTES);

        if (thinking == null) return null;
        UserVo userVo = userService.queryUser(thinking.getUserId());

        ThinkingVo thinkingVo = new ThinkingVo();
        BeanUtils.copyProperties(thinking, thinkingVo);
        thinkingVo.setOwner(userVo);

        return thinkingVo;
    }

    private List<Thinking> getThinkingPage(Map<String, Object> map) {
        Long id = (Long) map.get("id");
        Long startIdx = (Long) map.get("startIdx");
        int size = (int) map.get("size");
        return this.baseMapper.getPageByChannelId(id, startIdx, size);
    }

    @Override
    public ScrollPage<ThinkingVo> getPageByChannelId(Long channelId, Long max, int offset, int size) {
        String thinkingPageKey = RedisConstants.PAGE_THINKING_KEY + channelId;

        HashMap<String, Object> map = new HashMap<>();
        map.put("id", channelId);

        return cacheClient.queryScrollPage(thinkingPageKey, map, max, offset, size,
                this::getThinkingVoById, this::getThinkingPage, RedisConstants.COMMON_TTL, TimeUnit.MINUTES);
    }

    @Override
    public void updateWithCheckUser(Thinking thinking) {
        Long thinkingId = thinking.getThinkingId();
        Long userId = thinking.getUserId();
        if (thinkingId == null || userId == null) {
            throw new CustomException("缺少参数");
        }
        boolean b = this.updateById(thinking);
        if (!b) {
            throw new SqlException("修改帖子异常");
        }
    }

    @Override
    public boolean saveAndReview(Thinking thinking) {
        // 生成雪花id
        Snowflake snowflake = new Snowflake();
        long thinkingId = snowflake.nextId();
        thinking.setThinkingId(thinkingId);
        thinking.setStatus(2); // 设置审核中的状态
        thinking.setCreateTime(LocalDateTime.now());
        String thinkingJsonStr = JSON.toJSONString(thinking);
        // 存入redis
        String key = RedisConstants.THINKING_KEY + thinkingId;
        stringRedisTemplate.opsForValue().set(key, thinkingJsonStr);
        // 存入消息队列
        MqDTO mqDTO = new MqDTO(thinkingJsonStr, ModeType.SAVE);
        log.debug(String.valueOf(mqDTO));
        rabbitTemplate.convertAndSend(MQConstants.THINKING_KEY, mqDTO);

        // 返回添加成功
        return true;
    }
}




